/*
 * @Author: xiaosihan 
 * @Date: 2022-04-06 17:15:30 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2022-06-14 14:26:02
 */

import { ShaderChunk, BufferGeometry, Color, DoubleSide, Float32BufferAttribute, FrontSide, Mesh, NoBlending, OrthographicCamera, ShaderMaterial, Vector2, Vector3, WebGLRenderer } from "three";



// 全屏渲染模型对象
export const fullScreenMesh = new class FullScreenQuad {
    constructor() {
        this.mesh.geometry.setAttribute("position", new Float32BufferAttribute([- 1, 3, 0, - 1, - 1, 0, 3, - 1, 0], 3));
        this.mesh.geometry.setAttribute("uv", new Float32BufferAttribute([0, 2, 0, 0, 2, 0], 2));
    }

    mesh = new Mesh(new BufferGeometry());

    orthographicCamera = new OrthographicCamera(- 1, 1, 1, - 1, 0, 1);

    dispose() {
        this.mesh.geometry.dispose();
    }
    render(renderer: WebGLRenderer) {
        renderer.render(this.mesh, this.orthographicCamera);
    }
    get material() {
        return this.mesh.material;
    }
    set material(value) {
        this.mesh.material = value;
    }
}();

// 正方体 着色器
export const boxShader = new ShaderMaterial({
    uniforms: {
        color: { value: new Color("#1D3F65") },
        distanceToCenter: { value: 0 },
        gradientProgress: { value: 0 }, // 0 是纯蓝色 1是渐变色
        gradientColor1: { value: new Color("#ff0000") }, // 渐变色1
        gradientColor2: { value: new Color("#2A6BC7") }, // 渐变色2
        itmeMap: { value: null }, // 三级菜单需要用到的贴图
    },
    vertexShader: `
        ${ShaderChunk.common}
        ${ShaderChunk.logdepthbuf_pars_vertex}
        varying vec2 vUv;
        varying vec2 vUv2;
        void main() {
            vUv = uv;
            vUv2 = uv2;
            gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
            ${ShaderChunk.logdepthbuf_vertex}
        }
    `,
    fragmentShader: `
        ${ShaderChunk.logdepthbuf_pars_fragment}
        #include <common>
        uniform float distanceToCenter;
        uniform vec3 color;
        uniform float gradientProgress; // 渐变的进度
        uniform vec3 gradientColor1;
        uniform vec3 gradientColor2;
        uniform sampler2D itmeMap;
        varying vec2 vUv;
        varying vec2 vUv2;

        // 二维向量的绕点旋转的方法
        vec2 rotateAround( vec2 p, vec2 center, float angle ) {
            float c = cos( angle );
            float s = sin( angle );
            
            float x = p.x - center.x;
            float y = p.y - center.y;
    
            p.x = x * c - y * s + center.x;
            p.y = x * s + y * c + center.y;
    
            return p;
        }

        float opacity(){

            if(vUv2.y == 0.0){
                discard;
            }

            // return  vUv2.y == 1.0 ? 1.0 : clamp(0.0, 1.0, vUv.y * 2.0); 
            return  clamp(0.0, 1.0, vUv2.y * 2.0); 
        }

        vec3 fragColor(){
            return mix( color, vec3(0.0), distanceToCenter / 12.0 );
        }

        // 渐变色
        vec3 gradientColor(){

            vec3 gradienColor = mix(gradientColor1, gradientColor2,  vUv2.y >= 0.999 ? 0.0 : (1.0 - vUv.y) );

            // 白色的边
            if(vUv2.y >= 0.999){

                if(abs(vUv.x - 0.5) > 0.45 || abs(vUv.y - 0.5) > 0.45 ){
                    float width = max( abs(vUv.x - 0.5) , abs(vUv.y - 0.5) );
                    gradienColor = mix( 
                        gradienColor, 
                        vec3(1.0),  
                        smoothstep(0.45, 0.49, width) * 0.8
                    );  
                }

            }else if(vUv2.y == 0.0){

                gradienColor = vec3(0.0);

            }else if(vUv2.y < 1.0){
                    
                if( (abs(vUv.x - 0.5) - ((1.0-vUv.y) * 0.03) ) > 0.48 || (abs(vUv.y - 0.5) * (0.49 / 0.5)) > 0.48 ){

                    float width = max(
                        abs(vUv.x - 0.5) - ((1.0-vUv.y) * 0.03),
                        (abs(vUv.y - 0.5) * (0.49 / 0.5))
                    );

                    gradienColor = mix(
                        gradienColor, 
                        vec3(1.0),  
                        smoothstep(0.48, 0.49, width) * 0.8
                    );
                }
            }

            vec2 center = vec2(0.5);

            vec4 mapColor = texture2D(itmeMap, rotateAround( ((vUv - center) * 0.7071) + center , center, PI/-4.0 ) );

            // 三级菜单的贴图
            if(vUv2.y >= 0.9999){
                gradienColor = mix(gradienColor, mapColor.rgb, mapColor.a );
            }

            return gradienColor;
        }

        void main() {

            vec3 fragColor = mix( fragColor(), gradientColor(), gradientProgress );

            gl_FragColor = vec4( fragColor, opacity());
            ${ShaderChunk.logdepthbuf_fragment}
        }
    `,
    depthTest: true,
    depthWrite: true,
    transparent: true
});


// 中间大立方体着色器
export const centerBoxShader = new ShaderMaterial({
    uniforms: {
        color: { value: new Color("#8AE1EC") }
    },
    vertexShader: `
        ${ShaderChunk.common}
        ${ShaderChunk.logdepthbuf_pars_vertex}
        varying vec2 vUv;
        varying vec2 vUv2;
        attribute vec2 uv2;
        void main() {
            vUv = uv;
            vUv2 = uv2;
            gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
            ${ShaderChunk.logdepthbuf_vertex}
        }
    `,
    fragmentShader: `
        ${ShaderChunk.logdepthbuf_pars_fragment}
        uniform vec3 color;
        varying vec2 vUv;
        varying vec2 vUv2;

         float lineWidth = 0.1;
         float gridNum = 10.0;

        float opacity(){
            float upToDown = clamp(0.0, 1.0, vUv2.y * 2.0);
            return upToDown;
        }

        void main() {

            float o = opacity();

            if( 
                vUv2.y == 1.0
                && abs(fract(vUv.x * gridNum) - 0.5) < (0.5 - lineWidth)
                && abs(fract(vUv.y * gridNum) - 0.5) < (0.5 - lineWidth)
            ){
                o = 0.1;
            }
            
            if(
                vUv2.y < 1.0
                && abs(fract(vUv.x * gridNum) - 0.5) < (0.5 - lineWidth)
                && abs(fract(vUv2.y * gridNum) - 0.5) < (0.5 - (lineWidth/2.0))
            ){
                o = 0.1;
            }

            gl_FragColor = vec4(color, o );
            gl_FragColor = vec4(1.0, 1.0, 1.0, o);
            ${ShaderChunk.logdepthbuf_fragment}
        }
    `,
    // blending: NoBlending, // 渲染时不与背景融合计算 直接替换
    side: DoubleSide,
    depthTest: true,
    depthWrite: true,
    transparent: true
});

// 地板着色器 地板上面的有发散渐变效果
export const floorShader = new ShaderMaterial({
    uniforms: {
        gradientColor: { value: new Color("#2269C1") },
        center: { value: new Vector2(0.5, 0.5) },
        centerIndenty: { value: 1 }, // 中心点的渐变强度

        FealthCareCenter: { value: new Vector2(0.5 + 0.02, 0.5 - 0.03) }, // 医保监管指挥中心发散渐变的位置
        FealthCareCenterIndenty: { value: 0 }, // 医保监管指挥中心发散渐变强度0-1

        FundDetection: { value: new Vector2(0.5, 0.5 - 0.06) }, // 基金运行监测中心发散渐变的位置
        FundDetectionIndenty: { value: 0 }// 基金运行监测中心发散渐变强度0-1
    },
    vertexShader:
        `
        ${ShaderChunk.common}
        ${ShaderChunk.logdepthbuf_pars_vertex}
        varying vec2 vUv;
        void main() {
            vUv = uv;
            gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
            ${ShaderChunk.logdepthbuf_vertex}
        }
    `,
    fragmentShader: `
        ${ShaderChunk.logdepthbuf_pars_fragment}
        uniform vec3 gradientColor;
        
        uniform vec2 center;
        uniform float centerIndenty;
        
        uniform vec2 FealthCareCenter;
        uniform float FealthCareCenterIndenty;
        
        uniform vec2 FundDetection;
        uniform float FundDetectionIndenty;
        
        varying vec2 vUv;
        
        vec3 fragColor(){
        
        float d = min( 
            distance(center,  vUv ) + ((1.0 - centerIndenty) * 0.03),
            distance( FealthCareCenter, vUv ) + ((1.0 - FealthCareCenterIndenty) * 0.03)
            );
            
            d = min( 
                d, 
                distance( FundDetection, vUv ) + ((1.0 - FundDetectionIndenty) * 0.03) 
                );
                
                return mix(gradientColor , gradientColor * 0.2, smoothstep( d * 100.0, 0.0, 1.0 ) );
            }
            
        void main() {
            gl_FragColor = vec4( fragColor() , 1.0);
            ${ShaderChunk.logdepthbuf_fragment}
        }
    `,
    // blending: NoBlending, // 渲染时不与背景融合计算 直接替换
    depthTest: true,
    depthWrite: true,
    transparent: false
});

// 转场遮罩着色器
export const cutToShader = new ShaderMaterial({
    uniforms: {
        progress: { value: 0 }, // 转场进度
        resolution: { value: new Vector2(128, 128) }, // 分辨率
        center: { value: new Vector2(0.5, 0.5) }
    },
    vertexShader: `
        ${ShaderChunk.common}
        ${ShaderChunk.logdepthbuf_pars_vertex}
        varying vec2 vUv;
        void main() {
            vUv = uv;
            gl_Position = vec4(position, 1.0);
            ${ShaderChunk.logdepthbuf_vertex}
        }
    `,
    fragmentShader: `
        ${ShaderChunk.logdepthbuf_pars_fragment}
        #include <common>
        uniform float progress;
        uniform vec2 resolution;
        uniform vec2 center;
        varying vec2 vUv;

        void main() {

            vec2 uv = fract( vUv * 20.0 * vec2(resolution.x / resolution.y , 1.0) );

            if(
                fract( abs( uv.x - center.x)) > progress / 2.0 ||
                fract( abs( uv.y - center.y)) > progress / 2.0
            ){
                discard;
            }

            gl_FragColor = vec4(0.0);
            ${ShaderChunk.logdepthbuf_fragment}
        }
    `,
    blending: NoBlending, // 渲染时不与背景融合计算 直接替换
    depthTest: false,
    depthWrite: true,
    transparent: true
});